home *** CD-ROM | disk | FTP | other *** search
- Subject: v18i071: A ray-tracing package, Part02/03
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Mark VandeWettering <markv@drizzle.cs.uoregon.edu>
- Posting-number: Volume 18, Issue 71
- Archive-name: mtvraytrace/part02
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 3)."
- # Contents: NFF color.c cone.c intersect.c poly.c screen.c shade.c
- # tri.c
- # Wrapped by markv@tillamook on Mon Nov 14 12:50:26 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'NFF' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'NFF'\"
- else
- echo shar: Extracting \"'NFF'\" \(8711 characters\)
- sed "s/^X//" >'NFF' <<'END_OF_FILE'
- XFrom uoregon!uw-beaver!cornell!batcomputer!saponara Mon Oct 3 13:30:35 PDT 1988
- XArticle 3096 of comp.graphics:
- XPath: uoregon!uw-beaver!cornell!batcomputer!saponara
- X>From: saponara@batcomputer.tn.cornell.edu (John Saponara)
- XNewsgroups: comp.graphics
- XSubject: A description of NFF (Neutral File Format)
- XSummary: here you go...
- XKeywords: NFF, benchmark
- XMessage-ID: <6443@batcomputer.tn.cornell.edu>
- XDate: 3 Oct 88 19:57:58 GMT
- XReply-To: saponara@tcgould.tn.cornell.edu (Eric Haines, in truth)
- XOrganization: 3D/Eye Inc
- XLines: 235
- XReferences:
- XStatus: OR
- X
- XHere's my first draft, hot off the disk.
- X
- X Eric Haines (not John Saponara)
- X
- XNote: don't reply to me here, as this account disappears soon. Instead,
- X write me at hpfcla!hpfcrs!eye!erich@hplabs.hp.com
- X
- X-----------------------------------------------------------------------------
- X
- XNeutral File Format (NFF),
- X by Eric Haines, 3D/Eye Inc, 410 E Upland Rd, Ithaca, NY 14850
- X (607)-257-1381
- X email: hpfcla!hpfcrs!eye!erich@hplabs.hp.com
- X
- X
- X[This is a description of the format used in the SPD package. Any comments
- Xon how to expand this format are appreciated. Some extensions seem obvious
- Xto me (e.g. adding directional lights, circles, and tori), but I want to take
- Xmy time, gather opinions, and get it more-or-less right the first go round.
- XAlso, I'm ridiculously busy right now. -EAH]
- X
- XDraft document #1, 10/3/88
- X
- XThe NFF (Neutral File Format) is designed as a minimal scene description
- Xlanguage. The language was designed in order to test various rendering
- Xalgorithms and efficiency schemes. It is meant to describe the geometry and
- Xbasic surface characteristics of objects, the placement of lights, and the
- Xviewing frustum for the eye. Some additional information is provided for
- Xesthetic reasons (such as the color of the objects, which is not strictly
- Xnecessary for testing rendering algorithms).
- X
- XFuture enhancements include: circle and torus objects, spline surfaces
- Xwith trimming curves, directional lights, characteristics for positional
- Xlights, CSG descriptions, and probably more by the time you read this.
- XComments, suggestions, and criticisms are all welcome.
- X
- XAt present the NFF file format is used in conjunction with the SPD (Standard
- XProcedural Database) software, a package designed to create a variety of
- Xdatabases for testing rendering schemes. The SPD package is available
- Xfrom Netlib and via ftp from drizzle.cs.uoregon.edu. For more information
- Xabout SPD see "A Proposal for Standard Graphics Environments," IEEE Computer
- XGraphics and Applications, vol. 7, no. 11, November 1987, pp. 3-5.
- X
- XBy providing a minimal interface, NFF is meant to act as a simple format to
- Xallow the programmer to quickly write filters to move from NFF to the
- Xlocal file format. Presently the following entities are supported:
- X A simple perspective frustum
- X A positional (vs. directional) light source description
- X A background color description
- X A surface properties description
- X Polygon, polygonal patch, cylinder/cone, and sphere descriptions
- X
- XFiles are output as lines of text. For each entity, the first line
- Xdefines its type. The rest of the first line and possibly other lines
- Xcontain further information about the entity. Entities include:
- X
- X"v" - viewing vectors and angles
- X"l" - positional light location
- X"b" - background color
- X"f" - object material properties
- X"c" - cone or cylinder primitive
- X"s" - sphere primitive
- X"p" - polygon primitive
- X"pp" - polygonal patch primitive
- X
- X
- XThese are explained in depth below:
- X
- XViewpoint location. Description:
- X "v"
- X "from" Fx Fy Fz
- X "at" Ax Ay Az
- X "up" Ux Uy Uz
- X "angle" angle
- X "hither" hither
- X "resolution" xres yres
- X
- XFormat:
- X
- X v
- X from %g %g %g
- X at %g %g %g
- X up %g %g %g
- X angle %g
- X hither %g
- X resolution %d %d
- X
- XThe parameters are:
- X
- X From: the eye location in XYZ.
- X At: a position to be at the center of the image, in XYZ world
- X coordinates. A.k.a. "lookat".
- X Up: a vector defining which direction is up, as an XYZ vector.
- X Angle: in degrees, defined as from the center of top pixel row to
- X bottom pixel row and left column to right column.
- X Resolution: in pixels, in x and in y.
- X
- X Note that no assumptions are made about normalizing the data (e.g. the
- X from-at distance does not have to be 1). Also, vectors are not
- X required to be perpendicular to each other.
- X
- X For all databases some viewing parameters are always the same:
- X Yon is "at infinity."
- X Aspect ratio is 1.0.
- X
- X A view entity must be defined before any objects are defined (this
- X requirement is so that NFF files can be used by hidden surface machines).
- X
- X--------
- X
- XPositional light. A light is defined by XYZ position. Description:
- X "b" X Y Z
- X
- XFormat:
- X l %g %g %g
- X
- X All light entities must be defined before any objects are defined (this
- X requirement is so that NFF files can be used by hidden surface machines).
- X Lights have a non-zero intensity of no particular value [this definition
- X may change soon, with the addition of an intensity and/or color].
- X
- X--------
- X
- XBackground color. A color is simply RGB with values between 0 and 1:
- X "b" R G B
- X
- XFormat:
- X b %g %g %g
- X
- X If no background color is set, assume RGB = {0,0,0}.
- X
- X--------
- X
- XFill color and shading parameters. Description:
- X "f" red green blue Kd Ks Shine T index_of_refraction
- X
- XFormat:
- X f %g %g %g %g %g %g %g %g
- X
- X RGB is in terms of 0.0 to 1.0.
- X
- X Kd is the diffuse component, Ks the specular, Shine is the Phong cosine
- X power for highlights, T is transmittance (fraction of light passed per
- X unit). Usually, 0 <= Kd <= 1 and 0 <= Ks <= 1, though it is not required
- X that Kd + Ks == 1. Note that transmitting objects ( T > 0 ) are considered
- X to have two sides for algorithms that need these (normally objects have
- X one side).
- X
- X The fill color is used to color the objects following it until a new color
- X is assigned.
- X
- X--------
- X
- XObjects: all objects are considered one-sided, unless the second side is
- Xneeded for transmittance calculations (e.g. you cannot throw out the second
- Xintersection of a transparent sphere in ray tracing).
- X
- XCylinder or cone. A cylinder is defined as having a radius and an axis
- X defined by two points, which also define the top and bottom edge of the
- X cylinder. A cone is defined similarly, the difference being that the apex
- X and base radii are different. The apex radius is defined as being smaller
- X than the base radius. Note that the surface exists without endcaps. The
- X cone or cylinder description:
- X
- X "c"
- X base.x base.y base.z base_radius
- X apex.x apex.y apex.z apex_radius
- X
- XFormat:
- X c
- X %g %g %g %g
- X %g %g %g %g
- X
- X A negative value for both radii means that only the inside of the object is
- X visible (objects are normally considered one sided, with the outside
- X visible). Note that the base and apex cannot be coincident for a cylinder
- X or cone.
- X
- X--------
- X
- XSphere. A sphere is defined by a radius and center position:
- X "s" center.x center.y center.z radius
- X
- XFormat:
- X s %g %g %g %g
- X
- X If the radius is negative, then only the sphere's inside is visible
- X (objects are normally considered one sided, with the outside visible).
- X
- X--------
- X
- XPolygon. A polygon is defined by a set of vertices. With these databases,
- X a polygon is defined to have all points coplanar. A polygon has only
- X one side, with the order of the vertices being counterclockwise as you
- X face the polygon (right-handed coordinate system). The first two edges
- X must form a non-zero convex angle, so that the normal and side visibility
- X can be determined. Description:
- X
- X "p" total_vertices
- X vert1.x vert1.y vert1.z
- X [etc. for total_vertices vertices]
- X
- XFormat:
- X p %d
- X [ %g %g %g ] <-- for total_vertices vertices
- X
- X--------
- X
- XPolygonal patch. A patch is defined by a set of vertices and their normals.
- X With these databases, a patch is defined to have all points coplanar.
- X A patch has only one side, with the order of the vertices being
- X counterclockwise as you face the patch (right-handed coordinate system).
- X The first two edges must form a non-zero convex angle, so that the normal
- X and side visibility can be determined. Description:
- X
- X "pp" total_vertices
- X vert1.x vert1.y vert1.z norm1.x norm1.y norm1.z
- X [etc. for total_vertices vertices]
- X
- XFormat:
- X pp %d
- X [ %g %g %g %g %g %g ] <-- for total_vertices vertices
- X
- X--------
- X
- XComment. Description:
- X "#" [ string ]
- X
- XFormat:
- X # [ string ]
- X
- X As soon as a "#" character is detected, the rest of the line is considered
- X a comment.
- X
- X-------------------------------------------------------------------------------
- X
- X
- END_OF_FILE
- if test 8711 -ne `wc -c <'NFF'`; then
- echo shar: \"'NFF'\" unpacked with wrong size!
- fi
- # end of 'NFF'
- fi
- if test -f 'color.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'color.c'\"
- else
- echo shar: Extracting \"'color.c'\" \(6975 characters\)
- sed "s/^X//" >'color.c' <<'END_OF_FILE'
- X/***********************************************************************
- X * $Author: markv $
- X * $Revision: 1.2 $
- X * $Date: 88/09/12 12:53:47 $
- X * $Log: color.c,v $
- X * Revision 1.2 88/09/12 12:53:47 markv
- X * Fixed problem in LookupColorbyName, had return ; and return(0).
- X * [ Thank you lint! ]
- X *
- X * Revision 1.1 88/09/11 11:00:37 markv
- X * Initial revision
- X *
- X ***********************************************************************/
- X
- X#include <stdio.h>
- X#include "defs.h"
- X
- X#define NCOLORS (142)
- X
- Xtypedef struct t_color_entry {
- X char * ce_name ;
- X Vec ce_color ;
- X} ColorEntry ;
- X
- X#define LESS_THAN -1
- X#define GREATER_THAN 1
- X#define EQUAL_TO 0
- X
- X/*
- X * Note: These colors must be in sorted order, because we binary search
- X * for them.
- X *
- X * They were swiped from the X-11 distribution. Sorry....
- X */
- X
- XColorEntry Colors[] = {
- X "Aquamarine", {.439216, .858824, .576471},
- X "Black", {0, 0, 0},
- X "Blue", {0, 0, 1},
- X "BlueViolet", {.623529, .372549, .623529},
- X "Brown", {.647059, .164706, .164706},
- X "CadetBlue", {.372549, .623529, .623529},
- X "Coral", {1, .498039, 0},
- X "CornflowerBlue", {.258824, .258824, .435294},
- X "Cyan", {0, 1, 1},
- X "DarkGreen", {.184314, .309804, .184314},
- X "DarkOliveGreen", {.309804, .309804, .184314},
- X "DarkOrchid", {.6, .196078, .8},
- X "DarkSlateBlue", {.419608, .137255, .556863},
- X "DarkSlateGray", {.184314, .309804, .309804},
- X "DarkSlateGrey", {.184314, .309804, .309804},
- X "DarkTurquoise", {.439216, .576471, .858824},
- X "DimGray", {.329412, .329412, .329412},
- X "DimGrey", {.329412, .329412, .329412},
- X "Firebrick", {.556863, .137255, .137255},
- X "ForestGreen", {.137255, .556863, .137255},
- X "Gold", {.8, .498039, .196078},
- X "Goldenrod", {.858824, .858824, .439216},
- X "Gray", {.752941, .752941, .752941},
- X "Green", {0, 1, 0},
- X "GreenYellow", {.576471, .858824, .439216},
- X "Grey", {.752941, .752941, .752941},
- X "IndianRed", {.309804, .184314, .184314},
- X "Khaki", {.623529, .623529, .372549},
- X "LightBlue", {.74902, .847059, .847059},
- X "LightGray", {.658824, .658824, .658824},
- X "LightGrey", {.658824, .658824, .658824},
- X "LightSteelBlue", {.560784, .560784, .737255},
- X "LimeGreen", {.196078, .8, .196078},
- X "Magenta", {1, 0, 1},
- X "Maroon", {.556863, .137255, .419608},
- X "MediumAquamarine", {.196078, .8, .6},
- X "MediumBlue", {.196078, .196078, .8},
- X "MediumForestGreen", {.419608, .556863, .137255},
- X "MediumGoldenrod", {.917647, .917647, .678431},
- X "MediumOrchid", {.576471, .439216, .858824},
- X "MediumSeaGreen", {.258824, .435294, .258824},
- X "MediumSlateBlue", {.498039, 0, 1},
- X "MediumSpringGreen", {.498039, 1, 0},
- X "MediumTurquoise", {.439216, .858824, .858824},
- X "MediumVioletRed", {.858824, .439216, .576471},
- X "MidnightBlue", {.184314, .184314, .309804},
- X "Navy", {.137255, .137255, .556863},
- X "NavyBlue", {.137255, .137255, .556863},
- X "Orange", {.8, .196078, .196078},
- X "OrangeRed", {1, 0, .498039},
- X "Orchid", {.858824, .439216, .858824},
- X "PaleGreen", {.560784, .737255, .560784},
- X "Pink", {.737255, .560784, .560784},
- X "Plum", {.917647, .678431, .917647},
- X "Red", {1, 0, 0},
- X "Salmon", {.435294, .258824, .258824},
- X "SeaGreen", {.137255, .556863, .419608},
- X "Sienna", {.556863, .419608, .137255},
- X "SkyBlue", {.196078, .6, .8},
- X "SlateBlue", {0, .498039, 1},
- X "SpringGreen", {0, 1, .498039},
- X "SteelBlue", {.137255, .419608, .556863},
- X "Tan", {.858824, .576471, .439216},
- X "Thistle", {.847059, .74902, .847059},
- X "Turquoise", {.678431, .917647, .917647},
- X "Violet", {.309804, .184314, .309804},
- X "VioletRed", {.8, .196078, .6},
- X "Wheat", {.847059, .847059, .74902},
- X "White", {.988235, .988235, .988235},
- X "Yellow", {1, 1, 0},
- X "YellowGreen", {.6, .8, .196078},
- X "aquamarine", {.439216, .858824, .576471},
- X "black", {0, 0, 0},
- X "blue", {0, 0, 1},
- X "blue_violet", {.623529, .372549, .623529},
- X "brown", {.647059, .164706, .164706},
- X "cadet_blue", {.372549, .623529, .623529},
- X "coral", {1, .498039, 0},
- X "cornflower_blue", {.258824, .258824, .435294},
- X "cyan", {0, 1, 1},
- X "dark_green", {.184314, .309804, .184314},
- X "dark_olive_green", {.309804, .309804, .184314},
- X "dark_orchid", {.6, .196078, .8},
- X "dark_slate_blue", {.419608, .137255, .556863},
- X "dark_slate_gray", {.184314, .309804, .309804},
- X "dark_slate_grey", {.184314, .309804, .309804},
- X "dark_turquoise", {.439216, .576471, .858824},
- X "dim_gray", {.329412, .329412, .329412},
- X "dim_grey", {.329412, .329412, .329412},
- X "firebrick", {.556863, .137255, .137255},
- X "forest_green", {.137255, .556863, .137255},
- X "gold", {.8, .498039, .196078},
- X "goldenrod", {.858824, .858824, .439216},
- X "gray", {.752941, .752941, .752941},
- X "green", {0, 1, 0},
- X "green_yellow", {.576471, .858824, .439216},
- X "grey", {.752941, .752941, .752941},
- X "indian_red", {.309804, .184314, .184314},
- X "khaki", {.623529, .623529, .372549},
- X "light_blue", {.74902, .847059, .847059},
- X "light_gray", {.658824, .658824, .658824},
- X "light_grey", {.658824, .658824, .658824},
- X "light_steel_blue", {.560784, .560784, .737255},
- X "lime_green", {.196078, .8, .196078},
- X "magenta", {1, 0, 1},
- X "maroon", {.556863, .137255, .419608},
- X "medium_aquamarine", {.196078, .8, .6},
- X "medium_blue", {.196078, .196078, .8},
- X "medium_forest_green", {.419608, .556863, .137255},
- X "medium_goldenrod", {.917647, .917647, .678431},
- X "medium_orchid", {.576471, .439216, .858824},
- X "medium_sea_green", {.258824, .435294, .258824},
- X "medium_slate_blue", {.498039, 0, 1},
- X "medium_spring_green", {.498039, 1, 0},
- X "medium_turquoise", {.439216, .858824, .858824},
- X "medium_violet_red", {.858824, .439216, .576471},
- X "midnight_blue", {.184314, .184314, .309804},
- X "navy", {.137255, .137255, .556863},
- X "navy_blue", {.137255, .137255, .556863},
- X "orange", {.8, .196078, .196078},
- X "orange_red", {1, 0, .498039},
- X "orchid", {.858824, .439216, .858824},
- X "pale_green", {.560784, .737255, .560784},
- X "pink", {.737255, .560784, .560784},
- X "plum", {.917647, .678431, .917647},
- X "red", {1, 0, 0},
- X "salmon", {.435294, .258824, .258824},
- X "sea_green", {.137255, .556863, .419608},
- X "sienna", {.556863, .419608, .137255},
- X "sky_blue", {.196078, .6, .8},
- X "slate_blue", {0, .498039, 1},
- X "spring_green", {0, 1, .498039},
- X "steel_blue", {.137255, .419608, .556863},
- X "tan", {.858824, .576471, .439216},
- X "thistle", {.847059, .74902, .847059},
- X "turquoise", {.678431, .917647, .917647},
- X "violet", {.309804, .184314, .309804},
- X "violet_red", {.8, .196078, .6},
- X "wheat", {.847059, .847059, .74902},
- X "white", {.988235, .988235, .988235},
- X "yellow", {1, 1, 0},
- X "yellow_green", {.6, .8, .196078}
- X} ;
- X
- Xint
- XLookupColorByName(name, color)
- X char * name ;
- X Vec color ;
- X{
- X int rc ;
- X rc = BinarySearch(name, 0, NCOLORS - 1 , Colors) ;
- X if (rc < 0) {
- X return(0) ;
- X }
- X
- X VecCopy(Colors[rc].ce_color, color) ;
- X return 1 ;
- X}
- X
- X
- Xint
- XBinarySearch(name, l, h, array)
- X char * name ;
- X int l, h ;
- X ColorEntry array[] ;
- X{
- X int m, rc ;
- X if (l > h)
- X return(-1) ;
- X
- X m = (l + h) / 2 ;
- X
- X rc = strcmp(name, array[m].ce_name) ;
- X if (rc == 0)
- X return m ;
- X else if (rc < 0)
- X return BinarySearch(name, l, m-1, array) ;
- X else
- X return BinarySearch(name, m + 1, h, array) ;
- X}
- END_OF_FILE
- if test 6975 -ne `wc -c <'color.c'`; then
- echo shar: \"'color.c'\" unpacked with wrong size!
- fi
- # end of 'color.c'
- fi
- if test -f 'cone.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cone.c'\"
- else
- echo shar: Extracting \"'cone.c'\" \(6358 characters\)
- sed "s/^X//" >'cone.c' <<'END_OF_FILE'
- X/***********************************************************************
- X * $Author: markv $
- X * $Revision: 1.3 $
- X * $Date: 88/10/04 14:30:02 $
- X * $Log: cone.c,v $
- X * Revision 1.3 88/10/04 14:30:02 markv
- X * Fixed bug reported by koblas@mips.
- X *
- X * Revision 1.2 88/09/15 09:33:02 markv
- X * Fixed bug reported by koblas@mips. Cones which were specified with
- X * axis coincident with -y axis had problems. Caused by incorrect
- X * handling when finding orthogonal axes for the local coordinate system.
- X *
- X * Revision 1.1 88/09/11 11:00:38 markv
- X * Initial revision
- X *
- X ***********************************************************************/
- X#include <stdio.h>
- X#include <math.h>
- X#include "defs.h"
- X#include "extern.h"
- X
- Xtypedef struct t_conedata {
- X Vec cone_base ;
- X Flt cone_base_radius ;
- X Flt cone_base_d ;
- X Vec cone_apex ;
- X Flt cone_apex_radius ;
- X Vec cone_u ;
- X Vec cone_v ;
- X Vec cone_w ;
- X Flt cone_height ;
- X Flt cone_slope ;
- X Flt cone_min_d ;
- X Flt cone_max_d ;
- X} ConeData ;
- X
- Xint ConePrint ();
- Xint ConeIntersect ();
- Xint ConeNormal ();
- X
- XObjectProcs ConeProcs = {
- X ConePrint,
- X ConeIntersect,
- X ConeNormal,
- X} ;
- X
- Xint
- XConePrint(obj)
- X Object *obj ;
- X{
- X ConeData * cp ;
- X
- X cp = (ConeData *) obj -> o_data ;
- X
- X printf("c %g %g %g %g %g %g %g %g\n", cp -> cone_base[0],
- X cp -> cone_base[1],
- X cp -> cone_base[2],
- X cp -> cone_base_radius,
- X cp -> cone_apex[0],
- X cp -> cone_apex[1],
- X cp -> cone_apex[2],
- X cp -> cone_apex_radius) ;
- X}
- X
- XConeIntersect(obj, ray, hit)
- X Object * obj ;
- X Ray * ray ;
- X Isect * hit ;
- X{
- X Ray tray ;
- X ConeData * cd ;
- X Vec V, P ;
- X Flt a, b, c, d, disc ;
- X Flt t1, t2 ;
- X int nroots ;
- X
- X cd = (ConeData *) (obj -> o_data) ;
- X
- X /*
- X * First, we get the coordinates of the ray origin in
- X * the objects space....
- X */
- X
- X VecSub(ray -> P, cd -> cone_base, V) ;
- X
- X tray.P[0] = VecDot(V, cd -> cone_u) ;
- X tray.P[1] = VecDot(V, cd -> cone_v) ;
- X tray.P[2] = VecDot(V, cd -> cone_w) ;
- X
- X /*
- X VecAdd(ray -> P, ray -> D, V) ;
- X VecSub(V, cd -> cone_base, V) ;
- X */
- X
- X tray.D[0] = VecDot(ray -> D, cd -> cone_u) ;
- X tray.D[1] = VecDot(ray -> D, cd -> cone_v) ;
- X tray.D[2] = VecDot(ray -> D, cd -> cone_w) ;
- X
- X /*
- X VecSub(tray.D, tray.P, tray.D) ;
- X */
- X
- X a = tray.D[0] * tray.D[0]
- X + tray.D[1] * tray.D[1]
- X - cd -> cone_slope * cd -> cone_slope * tray.D[2] * tray.D[2] ;
- X
- X b = 2.0 * (tray.P[0] * tray.D[0] + tray.P[1] * tray.D[1] -
- X cd -> cone_slope * cd -> cone_slope * tray.P[2] * tray.D[2]
- X - cd -> cone_base_radius * cd -> cone_slope * tray.D[2]) ;
- X
- X c = cd -> cone_slope * tray.P[2] + cd -> cone_base_radius ;
- X c = tray.P[0] * tray.P[0] + tray.P[1] * tray.P[1] - (c * c) ;
- X
- X disc = b * b - 4.0 * a * c ;
- X
- X if (disc < 0.0)
- X return (0) ;
- X
- X disc = (Flt) sqrt(disc) ;
- X t1 = (-b - disc) / (2.0 * a) ;
- X t2 = (-b + disc) / (2.0 * a) ;
- X
- X if (t2 < rayeps)
- X return (0) ;
- X if (t1 < rayeps) {
- X nroots = 1 ;
- X t1 = t2 ;
- X } else {
- X nroots = 2 ;
- X }
- X
- X /*
- X * ensure that the points are between the two bounding planes...
- X */
- X
- X switch(nroots) {
- X case 1:
- X RayPoint(ray, t1, P) ;
- X d = VecDot(cd -> cone_w, P) ;
- X if (d >= cd -> cone_min_d && d <= cd -> cone_max_d) {
- X hit -> isect_t = t1 ;
- X hit -> isect_prim = obj ;
- X hit -> isect_surf = obj -> o_surf ;
- X hit -> isect_enter = 0 ;
- X return(1) ;
- X } else {
- X return(0) ;
- X }
- X break ;
- X case 2:
- X RayPoint(ray, t1, P) ;
- X d = VecDot(cd -> cone_w, P) ;
- X if (d >= cd -> cone_min_d && d <= cd -> cone_max_d) {
- X hit -> isect_t = t1 ;
- X hit -> isect_prim = obj ;
- X hit -> isect_surf = obj -> o_surf ;
- X hit -> isect_enter = 1 ;
- X return(1) ;
- X } else {
- X RayPoint(ray, t2, P) ;
- X d = VecDot(cd -> cone_w, P) ;
- X if (d >= cd -> cone_min_d && d <= cd -> cone_max_d) {
- X hit -> isect_t = t2 ;
- X hit -> isect_prim = obj ;
- X hit -> isect_surf = obj -> o_surf ;
- X hit -> isect_enter = 0 ;
- X return(1) ;
- X }
- X }
- X return(0) ;
- X }
- X return(0) ;
- X}
- X
- Xint
- XConeNormal(obj, hit, P, N)
- X Object * obj ;
- X Isect * hit ;
- X Point P, N ;
- X{
- X Flt t ;
- X Vec V ;
- X ConeData * cd ;
- X
- X cd = (ConeData *) obj -> o_data ;
- X
- X /*
- X * fill in the real normal...
- X * Project the point onto the base plane. The normal is
- X * a vector from the basepoint through this point, plus the slope
- X * times the cone_w vector...
- X */
- X
- X t = - (VecDot(P, cd -> cone_w) + cd -> cone_base_d) ;
- X VecAddS(t, cd -> cone_w, P, V) ;
- X VecSub(V, cd -> cone_base, N) ;
- X VecNormalize(N) ;
- X VecAddS(- cd -> cone_slope, cd -> cone_w, N, N) ;
- X VecNormalize(N) ;
- X}
- X
- XObject *
- XMakeCone(basepoint, baseradius, apexpoint, apexradius)
- X Vec basepoint, apexpoint ;
- X Flt baseradius, apexradius ;
- X{
- X Object * obj ;
- X ConeData * cd ;
- X Flt dmin, dmax, d , ftmp;
- X Vec tmp ;
- X int i ;
- X
- X obj = (Object *) malloc (sizeof (Object)) ;
- X obj -> o_type = T_CONE ;
- X obj -> o_procs = & ConeProcs ;
- X obj -> o_surf = CurrentSurface ;
- X
- X cd = (ConeData *) malloc (sizeof(ConeData)) ;
- X
- X VecCopy(basepoint, cd -> cone_base) ;
- X VecCopy(apexpoint, cd -> cone_apex) ;
- X
- X cd -> cone_base_radius = baseradius ;
- X cd -> cone_apex_radius = apexradius ;
- X
- X
- X VecSub(apexpoint, basepoint, cd -> cone_w) ;
- X cd -> cone_height = VecNormalize(cd -> cone_w) ;
- X cd -> cone_slope = (cd -> cone_apex_radius - cd -> cone_base_radius) /
- X (cd -> cone_height) ;
- X cd -> cone_base_d = - VecDot(basepoint, cd -> cone_w) ;
- X
- X MakeVector(0.0, 0.0, 1.0, tmp) ;
- X
- X if (1.0 - fabs(VecDot(tmp, cd -> cone_w)) < rayeps) {
- X MakeVector(0.0, 1.0, 0.0, tmp) ;
- X }
- X
- X /* find two axes which are at right angles to cone_w
- X */
- X
- X VecCross(cd -> cone_w, tmp, cd -> cone_u) ;
- X VecCross(cd -> cone_u, cd -> cone_w, cd -> cone_v) ;
- X
- X cd -> cone_min_d = VecDot(cd -> cone_w, cd -> cone_base) ;
- X cd -> cone_max_d = VecDot(cd -> cone_w, cd -> cone_apex) ;
- X
- X if (cd -> cone_max_d < cd -> cone_min_d) {
- X ftmp = cd -> cone_max_d ;
- X cd -> cone_max_d = cd -> cone_min_d ;
- X cd -> cone_min_d = ftmp ;
- X }
- X
- X obj -> o_data = (void *) cd ;
- X
- X for (i = 0 ; i < NSLABS ; i ++) {
- X dmin = HUGE ;
- X dmax = -HUGE ;
- X d = VecDot(basepoint, Slab[i]) - baseradius ;
- X if (d < dmin) dmin = d ; if (d > dmax) dmax = d ;
- X d = VecDot(basepoint, Slab[i]) + baseradius ;
- X if (d < dmin) dmin = d ; if (d > dmax) dmax = d ;
- X d = VecDot(apexpoint, Slab[i]) - apexradius ;
- X if (d < dmin) dmin = d ; if (d > dmax) dmax = d ;
- X d = VecDot(apexpoint, Slab[i]) + apexradius ;
- X if (d < dmin) dmin = d ; if (d > dmax) dmax = d ;
- X
- X obj -> o_dmin[i] = dmin ;
- X obj -> o_dmax[i] = dmax ;
- X }
- X
- X return(obj) ;
- X}
- END_OF_FILE
- if test 6358 -ne `wc -c <'cone.c'`; then
- echo shar: \"'cone.c'\" unpacked with wrong size!
- fi
- # end of 'cone.c'
- fi
- if test -f 'intersect.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'intersect.c'\"
- else
- echo shar: Extracting \"'intersect.c'\" \(4725 characters\)
- sed "s/^X//" >'intersect.c' <<'END_OF_FILE'
- X/***********************************************************************
- X * $Author: markv $
- X * $Revision: 1.2 $
- X * $Date: 88/09/12 12:54:48 $
- X * $Log: intersect.c,v $
- X * Revision 1.2 88/09/12 12:54:48 markv
- X * Added early cutoffs, as suggested by Haines in the RT-News, and
- X * independantly discovered by myself during our correspondence.
- X * Now, Intersect takes a max distance, and will not search for
- X * any intersections beyond the max distance.
- X * Also, to enable shadow caching, Shadow now returns the object
- X * that it found on its way to the light source.
- X *
- X * These optimizations speed up shadow testing considerably, and
- X * normal rays some small amount.
- X *
- X * Revision 1.1 88/09/11 11:00:40 markv
- X * Initial revision
- X *
- X ***********************************************************************/
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include <assert.h>
- X#include "defs.h"
- X#include "extern.h"
- X
- X/*
- X * intersect.c
- X * Much nicer now, uses the nifty priority queue search
- X * as suggested by Kajiya...
- X */
- X
- XFlt num[NSLABS] ;
- XFlt den[NSLABS] ;
- X
- X/***********************************************************************
- X * CheckAndEnqueue(obj, maxdist)
- X * Check the current ray (as paramaterized with the num and den
- X * arrays above) against the bounding volume of obj.
- X * If we intersect the bounding volume, then insert it into the
- X * priority queue.
- X *
- X * Note: should be broken into two separate procedures...
- X ***********************************************************************/
- X
- XINLINE
- XCheckAndEnqueue(obj, maxdist)
- X Object * obj ;
- X Flt maxdist ;
- X{
- X int i ;
- X Flt tmp ;
- X Flt tmin, tmax ;
- X Flt dmin = -HUGE ;
- X Flt dmax = maxdist ;
- X
- X nChecked ++ ;
- X
- X for (i = 0 ; i < NSLABS ; i ++) {
- X
- X /* enters the slab here... */
- X tmin = (obj -> o_dmin[i] - num[i]) * den[i] ;
- X /* and exits here... */
- X tmax = (obj -> o_dmax[i] - num[i]) * den[i] ;
- X
- X /* but we may have to swap... */
- X if (tmin > tmax) {
- X tmp = tmin ; tmin = tmax ; tmax = tmp ;
- X }
- X
- X /* if exited closer than we thought, update */
- X if (tmax < dmax)
- X dmax = tmax ;
- X /* if entered farther than we thought, update */
- X if (tmin > dmin)
- X dmin = tmin ;
- X
- X if (dmin > dmax || dmax < rayeps)
- X return ;
- X }
- X PriorityQueueInsert(dmin, obj) ;
- X nEnqueued ++ ;
- X}
- X
- X/***********************************************************************
- X * Intersect(ray, hit, maxdist)
- X *
- X * Returns true if we hit something in the root model closer than maxdist.
- X * Returns the closest hit in the "hit" buffer.
- X ***********************************************************************/
- X
- XIntersect(ray, hit, maxdist)
- X Ray * ray ;
- X Isect * hit ;
- X Flt maxdist ;
- X{
- X Isect nhit ;
- X int i ;
- X Flt min_dist = maxdist ;
- X Object * cobj ;
- X Object * pobj = NULL ;
- X CompositeData * cdp ;
- X Flt key ;
- X
- X /* If the object is simple, then return the hit that it gives you */
- X
- X if (Root -> o_type != T_COMPOSITE)
- X return (Root -> o_procs -> intersect) (Root, ray, hit) ;
- X
- X for (i = 0 ; i < NSLABS ; i ++) {
- X num[i] = VecDot(ray -> P, Slab[i]) ;
- X den[i] = 1.0 / VecDot(ray -> D, Slab[i]) ;
- X }
- X
- X /* start with an empty priority queue */
- X PriorityQueueNull() ;
- X
- X CheckAndEnqueue(Root, maxdist) ;
- X
- X for (;;) {
- X
- X if (PriorityQueueEmpty())
- X break ;
- X
- X PriorityQueueDelete(&key, &cobj) ;
- X
- X if (key > min_dist) {
- X
- X /*
- X * we have already found a primitive
- X * that was closer, we need look no further...
- X */
- X break ;
- X
- X } else if (cobj -> o_type == T_COMPOSITE) {
- X /*
- X * if it is in the queue, it got hit.
- X * check each of its children to see if their
- X * bounding volumes get hit.
- X * if so, then push them into the priority
- X * queue...
- X */
- X
- X cdp = (CompositeData *) cobj -> o_data ;
- X
- X for (i = 0 ; i < cdp -> c_size ; i ++ ) {
- X CheckAndEnqueue(cdp -> c_object[i], maxdist) ;
- X }
- X
- X } else {
- X
- X /*
- X * we have a primitive
- X * intersect with the primitive, and possibly
- X * update the nearest hit if it is indeed closer
- X * than the one we currently have...
- X */
- X
- X if ((cobj -> o_procs -> intersect) (cobj, ray, &nhit)) {
- X if (nhit.isect_t < min_dist) {
- X pobj = cobj ;
- X *hit = nhit ;
- X min_dist = nhit.isect_t ;
- X }
- X }
- X }
- X }
- X
- X if (pobj)
- X return 1 ;
- X else
- X return 0 ;
- X}
- X
- X/***********************************************************************
- X * Shadow(ray, hit, tmax)
- X *
- X * Returns true if we are unshadowed. Returns the primitive in
- X * the "hit" buffer.
- X *
- X * Note: the return value of this procedure is a bit strange, as well
- X * as the name. Should probably be changed.
- X ***********************************************************************/
- X
- Xint
- XShadow(ray, hit, tmax)
- X Ray * ray ;
- X Isect * hit ;
- X Flt tmax ;
- X{
- X if (Intersect(ray, hit, tmax))
- X return 0 ;
- X else
- X return 1 ;
- X}
- END_OF_FILE
- if test 4725 -ne `wc -c <'intersect.c'`; then
- echo shar: \"'intersect.c'\" unpacked with wrong size!
- fi
- # end of 'intersect.c'
- fi
- if test -f 'poly.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'poly.c'\"
- else
- echo shar: Extracting \"'poly.c'\" \(5428 characters\)
- sed "s/^X//" >'poly.c' <<'END_OF_FILE'
- X/***********************************************************************
- X * $Author: markv $
- X * $Revision: 1.2 $
- X * $Date: 88/10/04 14:32:25 $
- X * $Log: poly.c,v $
- X * Revision 1.2 88/10/04 14:32:25 markv
- X * Renamed p1 and p2 to be poly_u and poly_v, which are better names.
- X * Also may have solved problems having to do with floating point roundoff
- X * when planes are parallel to bounding slabs.
- X *
- X * Revision 1.1 88/09/11 11:00:42 markv
- X * Initial revision
- X *
- X ***********************************************************************/
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include "defs.h"
- X#include "extern.h"
- X
- Xtypedef struct t_polydata {
- X int poly_npoints ;
- X Vec * poly_point ;
- X Vec poly_normal ;
- X Flt poly_d ;
- X Flt poly_u, poly_v ;
- X} PolyData ;
- X
- Xint PolyPrint ();
- Xint PolyIntersect ();
- Xint PolyNormal ();
- X
- XObjectProcs PolyProcs = {
- X PolyPrint,
- X PolyIntersect,
- X PolyNormal,
- X} ;
- X
- Xint
- XPolyPrint(obj)
- X Object * obj ;
- X{
- X int i ;
- X PolyData * pd ;
- X
- X pd = (PolyData *) obj -> o_data ;
- X printf("p %d\n", pd -> poly_npoints) ;
- X for (i = 0 ; i < pd -> poly_npoints ; i++) {
- X printf("%g %g %g\n", pd -> poly_point[i][0],
- X pd -> poly_point[i][1],
- X pd -> poly_point[i][2]) ;
- X }
- X}
- X
- X/***********************************************************************
- X * PolyIntersect(obj, ray, hit)
- X *
- X * returns 1 if we hit the polygon, with the hit information in hit.
- X * Uses a version of Jordan's theorem to determine whether the point
- X * is inside the polygon.
- X * The variable "crosses" will count the number of times that we
- X * cross the boundary of the curve. If it is odd, we are inside.
- X *
- X ***********************************************************************/
- X
- XPolyIntersect(obj, ray, hit)
- X Object * obj ;
- X Ray * ray ;
- X Isect * hit ;
- X{
- X Flt n,d,t,m,b ;
- X Point V ;
- X int i, j, crosses = 0 ;
- X int qi, qj ;
- X int ri, rj ;
- X int u, v ;
- X PolyData * pd ;
- X
- X pd = (PolyData *) obj -> o_data ;
- X n = VecDot(ray -> P, pd -> poly_normal) + pd -> poly_d ;
- X d = VecDot(ray -> D, pd -> poly_normal) ;
- X
- X if ((Flt) fabs(d) < rayeps) {
- X return (0) ;
- X }
- X
- X t = - n / d ;
- X if (t < rayeps)
- X return 0 ;
- X
- X RayPoint(ray,t,V);
- X
- X u = pd -> poly_u ;
- X v = pd -> poly_v ;
- X
- X for (i = 0 ; i < pd -> poly_npoints ; i++) {
- X
- X j = (i + 1) % pd -> poly_npoints ;
- X
- X qi = 0 ; qj = 0 ;
- X ri = 0 ; rj = 0 ;
- X
- X if (pd -> poly_point[i][v] == pd -> poly_point[j][v])
- X continue ; /*ignore horizontal lines */
- X
- X /*
- X * If we are both above, or both below the intersection point,
- X * go onto the next one.
- X */
- X
- X if (pd -> poly_point[i][v] < V[v])
- X qi = 1 ;
- X if (pd -> poly_point[j][v] < V[v])
- X qj = 1 ;
- X if (qi == qj)
- X continue ;
- X
- X /*
- X * We know one end point was above, and one was below.
- X * If theyare both to the left, then we crossed the line
- X * to negative infinity, and we continue.
- X */
- X if (pd -> poly_point[i][u] < V[u])
- X ri = 1 ;
- X if (pd -> poly_point[j][u] < V[u])
- X rj = 1 ;
- X
- X if (ri & rj) {
- X crosses ++ ;
- X continue ;
- X }
- X
- X /*
- X * Otherwise, if we are both to the right,
- X * we can continue without a cross.
- X */
- X
- X if ((ri|rj) == 0)
- X continue ;
- X
- X
- X /*
- X * more difficult acceptance...
- X * We have a line segment which occurs with endpoints
- X * in diagonally opposite quadrants. We must solve
- X * for the intersection, ie, where v = 0.
- X */
- X
- X m = (pd -> poly_point[j][v] - pd -> poly_point[i][v]) /
- X (pd -> poly_point[j][u] - pd -> poly_point[i][u]) ;
- X
- X b = (pd -> poly_point[j][v] - V[v]) -
- X m * (pd -> poly_point[j][u] - V[u]);
- X
- X if ((-b/m) < rayeps)
- X crosses ++ ;
- X }
- X
- X if (crosses & 1) {
- X hit -> isect_t = t ;
- X hit -> isect_surf = obj -> o_surf ;
- X hit -> isect_prim = obj ;
- X hit -> isect_enter = 0 ;
- X return(1);
- X } else {
- X return(0);
- X }
- X}
- X
- XPolyNormal(obj, hit, P, N)
- X Object * obj ;
- X Isect * hit ;
- X Point P, N ;
- X{
- X
- X PolyData * pd ;
- X pd = (PolyData *) obj -> o_data ;
- X VecCopy(pd -> poly_normal, N);
- X}
- X
- XObject *
- XMakePoly(npoints, points)
- X int npoints ;
- X Vec * points ;
- X{
- X Object * obj ;
- X PolyData * pd ;
- X Vec P1, P2 ;
- X Flt d, dmax, dmin ;
- X int i, j ;
- X
- X obj = (Object *) malloc (sizeof(Object)) ;
- X obj -> o_type = T_POLY ;
- X obj -> o_procs = & PolyProcs ;
- X obj -> o_surf = CurrentSurface ;
- X
- X pd = (PolyData *) malloc (sizeof(PolyData)) ;
- X pd -> poly_npoints = npoints ;
- X pd -> poly_point = points ;
- X
- X /*
- X * calculate the normal by giving various cross products...
- X */
- X
- X VecSub(pd -> poly_point[0], pd -> poly_point[1], P1) ;
- X VecSub(pd -> poly_point[2], pd -> poly_point[1], P2) ;
- X
- X VecCross(P1, P2, pd -> poly_normal) ;
- X VecNormalize(pd -> poly_normal) ;
- X
- X if (fabs(pd -> poly_normal[0]) > fabs(pd -> poly_normal[1])
- X && fabs(pd -> poly_normal[0]) > fabs(pd -> poly_normal[2])) {
- X pd -> poly_u = 1 ;
- X pd -> poly_v = 2 ;
- X } else if (fabs(pd -> poly_normal[1]) > fabs(pd -> poly_normal[0])
- X && fabs(pd -> poly_normal[1]) > fabs(pd -> poly_normal[2])) {
- X pd -> poly_u = 0 ;
- X pd -> poly_v = 2 ;
- X } else {
- X pd -> poly_u = 0 ;
- X pd -> poly_v = 1 ;
- X }
- X
- X pd -> poly_d = - VecDot(pd -> poly_normal, pd -> poly_point[0]) ;
- X
- X obj -> o_data = (void *) pd ;
- X
- X /*
- X * now, calculate the values of
- X * the dmin and dmax 'es for the globally defined slabs...
- X */
- X
- X for (i = 0 ; i < NSLABS ; i ++) {
- X dmin = HUGE ;
- X dmax = - HUGE ;
- X
- X for (j = 0 ; j < pd -> poly_npoints ; j ++) {
- X d = VecDot(Slab[i], pd -> poly_point[j]) ;
- X if (d < dmin) dmin = d ;
- X if (d > dmax) dmax = d ;
- X }
- X obj -> o_dmin[i] = dmin - rayeps ;
- X obj -> o_dmax[i] = dmax + rayeps ;
- X }
- X return(obj) ;
- X}
- END_OF_FILE
- if test 5428 -ne `wc -c <'poly.c'`; then
- echo shar: \"'poly.c'\" unpacked with wrong size!
- fi
- # end of 'poly.c'
- fi
- if test -f 'screen.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'screen.c'\"
- else
- echo shar: Extracting \"'screen.c'\" \(5370 characters\)
- sed "s/^X//" >'screen.c' <<'END_OF_FILE'
- X/***********************************************************************
- X * $Author: markv $
- X * $Revision: 1.3 $
- X * $Date: 88/10/04 14:33:37 $
- X * $Log: screen.c,v $
- X * Revision 1.3 88/10/04 14:33:37 markv
- X * Revamped most of this code. Added code for no antialiasing, jittering,
- X * filtered, and statistically optimized antialiasing. Statistically
- X * optimized anti aliasing still doesn't work properly.
- X *
- X * Revision 1.2 88/09/12 10:00:54 markv
- X * Fixed lingering (possible) bug with curbuf memory allocation.
- X * Size returned by malloc is now correct in both spots.
- X * Thanks tim@ben.
- X *
- X * Revision 1.1 88/09/11 11:00:43 markv
- X * Initial revision
- X *
- X ***********************************************************************/
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include <assert.h>
- X#include "defs.h"
- X#include "pic.h"
- X#include "extern.h"
- X
- XScreen(view, picfile, xres, yres)
- X Viewpoint *view ;
- X char *picfile ;
- X int xres, yres ;
- X{
- X Pixel *buf, *oldbuf, *curbuf, *tmp ;
- X Pic *pic, *PicOpen();
- X Point viewvec, leftvec, upvec ;
- X int red, green, blue ;
- X Point dir ;
- X Ray ray ;
- X Color color;
- X Flt frustrumwidth ;
- X int x, y ;
- X
- X pic = PicOpen(picfile, xres, yres) ;
- X
- X /*
- X * calculate the "up" vector...
- X */
- X
- X VecCopy(view -> view_up, upvec) ;
- X VecNormalize(upvec) ;
- X
- X /*
- X * and the "view" vector....
- X */
- X
- X VecSub(view -> view_at, view-> view_from, viewvec);
- X VecNormalize(viewvec);
- X
- X /*
- X * And the "left" vector...
- X */
- X
- X VecCross(view -> view_up, viewvec, leftvec);
- X VecNormalize(leftvec);
- X
- X /*
- X * Calculate the width of the view frustrum in world coordinates.
- X * and then scale the left and up vectors appropriately.
- X */
- X
- X frustrumwidth = (view -> view_dist) * ((Flt) tan(view -> view_angle)) ;
- X VecScale(-frustrumwidth, upvec) ;
- X VecScale(-frustrumwidth, leftvec) ;
- X
- X if (filtflag) {
- X FilterScan( pic,
- X view -> view_from,
- X viewvec,
- X upvec,
- X leftvec,
- X xres, yres) ;
- X } else if (jitterflag) {
- X JitterScan( pic,
- X view -> view_from,
- X viewvec,
- X upvec,
- X leftvec,
- X xres, yres) ;
- X } else {
- X Scan( pic,
- X view -> view_from,
- X viewvec,
- X upvec,
- X leftvec,
- X xres, yres) ;
- X }
- X
- X PicClose(pic) ;
- X}
- X
- X
- X
- X
- XScan(pic, eye, viewvec, upvec, leftvec, xres, yres)
- X Pic * pic ;
- X Vec eye ;
- X Vec viewvec ;
- X Vec upvec ;
- X Vec leftvec ;
- X int xres, yres ;
- X{
- X Ray ray ;
- X int x, y ;
- X Flt xlen, ylen ;
- X Color color ;
- X
- X /*
- X * Generate the image...
- X */
- X
- X VecCopy(eye, ray.P) ;
- X for (y = 0 ; y < yres ; y++) {
- X for (x = 0 ; x < xres ; x++) {
- X xlen = ((Flt) (2 * x) / (Flt) xres) - 1.0 ;
- X ylen = ((Flt) (2 * y) / (Flt) yres) - 1.0 ;
- X VecComb(xlen, leftvec, ylen, upvec, ray.D) ;
- X VecAdd(ray.D, viewvec, ray.D) ;
- X VecNormalize(ray.D);
- X Trace(0, 1.0, &ray, color);
- X color[0] = min(1.0, color[0]) ;
- X color[1] = min(1.0, color[1]) ;
- X color[2] = min(1.0, color[2]) ;
- X PicWritePixel(pic, color) ;
- X }
- X if (tickflag)
- X fprintf(stderr, ".") ;
- X }
- X if (tickflag)
- X fprintf(stderr, "\n") ;
- X}
- X
- XFilterScan(pic, eye, viewvec, upvec, leftvec, xres, yres)
- X Pic * pic ;
- X Vec eye ;
- X Vec viewvec ;
- X Vec upvec ;
- X Vec leftvec ;
- X int xres, yres ;
- X{
- X Ray ray ;
- X int x, y, i ;
- X Flt xlen, ylen ;
- X Color color ;
- X Color * nbuf, *obuf, *tmp ; /* new and old buffers, resp. */
- X Color avg ;
- X
- X /*
- X * allocate enough memory for the filter buffer
- X */
- X
- X nbuf = (Color *) calloc ((xres + 1), sizeof(Color)) ;
- X obuf = NULL ;
- X
- X VecCopy(eye, ray.P) ;
- X
- X for (y = 0 ; y <= yres ; y++) {
- X for (x = 0 ; x <= xres ; x++) {
- X xlen = ((Flt) (2 * x) / (Flt) xres) - 1.0 ;
- X ylen = ((Flt) (2 * y) / (Flt) yres) - 1.0 ;
- X VecComb(xlen, leftvec, ylen, upvec, ray.D) ;
- X VecAdd(ray.D, viewvec, ray.D) ;
- X VecNormalize(ray.D);
- X Trace(0, 1.0, &ray, color);
- X color[0] = min(1.0, color[0]) ;
- X color[1] = min(1.0, color[1]) ;
- X color[2] = min(1.0, color[2]) ;
- X VecCopy(color, nbuf[x]) ;
- X }
- X if (obuf) {
- X for (i = 0 ; i < xres ; i++) {
- X VecAdd(nbuf[i], nbuf[i+1], avg) ;
- X VecAdd(obuf[i], avg, avg) ;
- X VecAdd(obuf[i+1], avg, avg) ;
- X VecScale(0.25, avg) ;
- X PicWritePixel(pic, avg) ;
- X }
- X tmp = obuf ;
- X obuf = nbuf ;
- X nbuf = tmp ;
- X } else {
- X /*
- X * first scan line, set it up wierdly...
- X */
- X obuf = nbuf ;
- X nbuf = (Color *) calloc ((xres + 1), sizeof(Color)) ;
- X }
- X if (tickflag)
- X fprintf(stderr, ".") ;
- X }
- X if (tickflag)
- X fprintf(stderr, "\n") ;
- X}
- X
- XJitterScan(pic, eye, viewvec, upvec, leftvec, xres, yres)
- X Pic * pic ;
- X Vec eye ;
- X Vec viewvec ;
- X Vec upvec ;
- X Vec leftvec ;
- X int xres, yres ;
- X{
- X Ray ray ;
- X int x, y, i ;
- X Flt xlen, ylen ;
- X Flt xwidth, ywidth ;
- X Color color, avg ;
- X
- X /*
- X * Generate the image...
- X */
- X
- X xwidth = 2.0 / (Flt) xres ;
- X ywidth = 2.0 / (Flt) xres ;
- X
- X VecCopy(eye, ray.P) ;
- X for (y = 0 ; y < yres ; y++) {
- X ylen = ((Flt) (2 * y) / (Flt) yres) - 1.0 ;
- X for (x = 0 ; x < xres ; x++) {
- X xlen = ((Flt) (2 * x) / (Flt) xres) - 1.0 ;
- X
- X avg[0] = avg[1] = avg[2] = 0.0 ;
- X
- X for (i = 0 ; i < maxsamples ; i++) {
- X VecComb(xlen + rnd() * xwidth, leftvec,
- X ylen + rnd() * ywidth, upvec, ray.D) ;
- X VecAdd(ray.D, viewvec, ray.D) ;
- X VecNormalize(ray.D);
- X Trace(0, 1.0, &ray, color);
- X VecAdd(color, avg, avg) ;
- X }
- X
- X VecScale(1.0 / (Flt) maxsamples, avg) ;
- X avg[0] = min(1.0, avg[0]) ;
- X avg[1] = min(1.0, avg[1]) ;
- X avg[2] = min(1.0, avg[2]) ;
- X PicWritePixel(pic, avg) ;
- X }
- X if (tickflag)
- X fprintf(stderr, ".") ;
- X }
- X if (tickflag)
- X fprintf(stderr, "\n") ;
- X}
- END_OF_FILE
- if test 5370 -ne `wc -c <'screen.c'`; then
- echo shar: \"'screen.c'\" unpacked with wrong size!
- fi
- # end of 'screen.c'
- fi
- if test -f 'shade.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'shade.c'\"
- else
- echo shar: Extracting \"'shade.c'\" \(4575 characters\)
- sed "s/^X//" >'shade.c' <<'END_OF_FILE'
- X/***********************************************************************
- X * $Author: markv $
- X * $Revision: 1.2 $
- X * $Date: 88/09/12 12:58:01 $
- X * $Log: shade.c,v $
- X * Revision 1.2 88/09/12 12:58:01 markv
- X * Added specular reflections and shadow caching. When a object
- X * is found between a light source and the current point we are trying
- X * to shade, that object is cached (indexed by recursion level) in the
- X * lightsource. Next time we test a shadow against the light source,
- X * we test this object first. If it is between us and the light source,
- X * we can correctly shadow the object without calling Intersect().
- X *
- X * Note: specular highlights call the unix pow() function, which seems
- X * to be REALLY expensive. Optimizations could be made here.
- X *
- X * Revision 1.1 88/09/11 11:00:44 markv
- X * Initial revision
- X *
- X ***********************************************************************/
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include "defs.h"
- X#include "extern.h"
- X
- X/***********************************************************************
- X * Shade(level, weight, P, N, I, hit, col)
- X *
- X * Wow! Too many parameters!
- X *
- X * Shade is the driving force of the raytracer. It calculates the actual
- X * luminance at point P, given N, the normal, and I the incident vector.
- X * We also pass in the hit, because the normal generating code might need it.
- X * The color is returned in col.
- X ***********************************************************************/
- X
- XShade(level, weight, P, N, I, hit, col)
- X int level ;
- X Flt weight ;
- X Vec P, N, I ;
- X Isect * hit;
- X Color col ;
- X{
- X Ray tray ;
- X Color tcol ;
- X Vec L, H, R ;
- X Flt t ;
- X Flt diff ;
- X Flt spec ;
- X#ifdef SHADOW_CACHING
- X Object * cached ;
- X#endif /* SHADOW_CACHING */
- X Isect nhit ;
- X Surface * surf ;
- X int l ;
- X
- X col[0] = col[1] = col[2] = 0.0 ;
- X surf = hit -> isect_prim -> o_surf ;
- X
- X for (l = 0; l < nLights; l++) {
- X VecSub(Lights[l].light_pos, P, L);
- X if (VecDot(N,L) >= 0.0) {
- X t = VecNormalize(L);
- X VecCopy(P, tray.P);
- X VecCopy(L, tray.D);
- X nShadows ++ ;
- X#ifdef SHADOW_CACHING
- X cached = Lights[l].light_obj_cache[level] ;
- X if (cached
- X && (cached -> o_procs -> intersect)
- X (cached, &tray, &nhit)
- X && nhit.isect_t < t) {
- X /*
- X * we are in shadow, continue...
- X */
- X nShadowCacheHits ++ ;
- X continue ;
- X }
- X#endif /* SHADOW_CACHING */
- X if (Shadow(&tray, &nhit, t)) {
- X diff = VecDot(N,L) * surf -> surf_kd
- X * Lights[l].light_brightness ;
- X#ifdef SHADOW_CACHING
- X Lights[l].light_obj_cache[level] = NULL ;
- X#endif /* SHADOW_CACHING */
- X VecAddS(diff, surf -> surf_color, col, col) ;
- X SpecularDirection(I, N, R) ;
- X VecNormalize(R) ;
- X if (surf -> surf_shine > rayeps) {
- X spec = VecDot(R,L) ;
- X if (spec > rayeps) {
- X spec = pow(spec, surf -> surf_shine ) * Lights[l].light_brightness ;
- X col[0] += spec ;
- X col[1] += spec ;
- X col[2] += spec ;
- X }
- X }
- X } else {
- X#ifdef SHADOW_CACHING
- X Lights[l].light_obj_cache[level] =
- X nhit.isect_prim ;
- X#endif /* SHADOW_CACHING */
- X }
- X
- X }
- X }
- X
- X VecCopy(P, tray.P);
- X
- X if(surf -> surf_ks * weight > minweight) {
- X nReflected ++ ;
- X SpecularDirection(I, N, tray.D);
- X VecNormalize(tray.D);
- X Trace(level + 1, surf -> surf_ks * weight, &tray, tcol);
- X VecAddS(surf -> surf_ks, tcol, col, col);
- X }
- X
- X if (surf -> surf_kt * weight > minweight) {
- X nRefracted ++ ;
- X if (hit -> isect_enter)
- X TransmissionDirection(NULL, surf, I, N, tray.D) ;
- X else
- X TransmissionDirection(surf, NULL, I, N, tray.D) ;
- X Trace(level + 1, surf -> surf_kt * weight, &tray, tcol) ;
- X VecAddS(surf -> surf_kt, tcol, col, col) ;
- X }
- X}
- X
- X/***********************************************************************
- X * SpecularDirection(I, N, R)
- X *
- X * Given an incident vector I, and the normal N, calculate the
- X * direction of the reflected ray R.
- X ***********************************************************************/
- X
- XSpecularDirection(I, N, R)
- X Vec I, N, R;
- X{
- X VecComb(1.0/fabs(VecDot(I,N)), I, 2.0, N, R);
- X VecNormalize(R);
- X}
- X
- X/***********************************************************************
- X * TransmissionDirection(m1, m2, I, N, T)
- X *
- X * calculates the direction of the transmitted ray
- X ***********************************************************************/
- X
- XTransmissionDirection(m1, m2, I, N, T)
- X Surface *m1, *m2;
- X Vec I, N, T ;
- X{
- X Flt n1, n2, eta, c1, cs2 ;
- X n1 = m1 ? m1 -> surf_ior : 1.0 ;
- X n2 = m2 ? m2 -> surf_ior : 1.0 ;
- X eta = n1/n2 ;
- X
- X c1 = -VecDot(I,N);
- X cs2 = 1.0 - eta * eta*(1.0 - c1*c1);
- X if (cs2 < 0.0)
- X return 0;
- X VecComb(eta, I, eta*c1-sqrt(cs2), N, T);
- X return(1);
- X}
- END_OF_FILE
- if test 4575 -ne `wc -c <'shade.c'`; then
- echo shar: \"'shade.c'\" unpacked with wrong size!
- fi
- # end of 'shade.c'
- fi
- if test -f 'tri.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'tri.c'\"
- else
- echo shar: Extracting \"'tri.c'\" \(6022 characters\)
- sed "s/^X//" >'tri.c' <<'END_OF_FILE'
- X/***********************************************************************
- X * $Author: markv $
- X * $Revision: 1.1 $
- X * $Date: 88/11/12 16:23:13 $
- X * $Log: tri.c,v $
- X * Revision 1.1 88/11/12 16:23:13 markv
- X * Initial revision
- X *
- X * TRIs are triangular patches with normals defined at the vertices.
- X * When an intersection is found, it interpolates the normal to the
- X * surface at that point.
- X *
- X * Algorithm is due to Jeff Arenburg, (arenburg@trwrb.uucp) and was
- X * posted to USENET.
- X *
- X * Basically, for each triangle we calculate an inverse transformation
- X * matrix, and use it to determine the point of intersection in the plane
- X * of the triangle relative to the "base point" of the triangle. We then
- X * figure its coordinates relative to that base point. These base points
- X * are used to find the barycentric coordinates, and then in normal
- X * interpolation...
- X ***********************************************************************/
- X
- X#include <stdio.h>
- X#include <math.h>
- X#include "defs.h"
- X#include "extern.h"
- X
- Xtypedef struct t_spheredata {
- X Vec tri_P[3] ;
- X Vec tri_N[3] ;
- X Vec tri_bb[3] ;
- X} TriData ;
- X
- Xint TriPrint ();
- Xint TriIntersect ();
- Xint TriNormal ();
- X
- XObjectProcs TriProcs = {
- X TriPrint,
- X TriIntersect,
- X TriNormal,
- X} ;
- X
- Xint
- XTriPrint(obj)
- X Object *obj ;
- X{
- X TriData *td ;
- X int i ;
- X
- X td = (TriData *) obj -> o_data ;
- X printf("pp 3\n") ;
- X for (i = 0 ; i < 3 ; i ++) {
- X VecPrint("\t", td -> tri_P[i]) ;
- X VecPrint("\t", td -> tri_N[i]) ;
- X }
- X}
- X
- XTriIntersect(obj, ray, hit)
- X Object * obj ;
- X Ray * ray ;
- X Isect * hit ;
- X{
- X TriData *td ;
- X Flt n, d, dist ;
- X Flt r, s, t ;
- X Flt a, b ;
- X Vec P, Q ;
- X
- X td = (TriData *) obj -> o_data ;
- X
- X /*
- X * The matrix td -> tri_bb transforms vectors in the world
- X * space into a space with the following properties.
- X *
- X * 1. The sides of the triangle are coincident with the
- X * x and y axis, and have unit length.
- X * 2. The normal to the triangle is coincident with the
- X * z axis.
- X *
- X */
- X
- X /*
- X * d is the slope with respect to the z axis. If d is zero, then
- X * the ray is parallel to the plane of the polygon, and we count
- X * it as a miss...
- X */
- X
- X d = VecDot(ray -> D, td -> tri_bb[2]) ;
- X if (fabs(d) < rayeps)
- X return 0 ;
- X
- X /*
- X * Q is a vector from the eye to the triangles "origin" vertex.
- X * n is then set to be the distance of the tranformed eyepoint
- X * to the plane in the polygon.
- X * Together, n and d allow you to find the distance to the polygon,
- X * which is merely n / d.
- X */
- X
- X VecSub(td -> tri_P[0], ray -> P, Q) ;
- X
- X n = VecDot(Q, td -> tri_bb[2]) ;
- X
- X dist = n / d ;
- X
- X if (dist < rayeps)
- X return 0 ;
- X
- X /*
- X * Q is the point we hit. Find its position relative to the
- X * origin of the triangle.
- X */
- X
- X RayPoint(ray, dist, Q) ;
- X VecSub(Q, td -> tri_P[0], Q) ;
- X
- X a = VecDot(Q, td -> tri_bb[0]) ;
- X b = VecDot(Q, td -> tri_bb[1]) ;
- X
- X if (a < 0.0 || b < 0.0 || a + b > 1.0)
- X return 0 ;
- X
- X r = 1.0 - a - b ;
- X s = a ;
- X t = b ;
- X
- X hit -> isect_t = dist ;
- X hit -> isect_enter = 0 ;
- X hit -> isect_prim = obj ;
- X hit -> isect_surf = obj -> o_surf ;
- X
- X VecZero(hit->isect_normal) ;
- X VecAddS(r, td -> tri_N[0], hit -> isect_normal, hit -> isect_normal) ;
- X VecAddS(s, td -> tri_N[1], hit -> isect_normal, hit -> isect_normal) ;
- X VecAddS(t, td -> tri_N[2], hit -> isect_normal, hit -> isect_normal) ;
- X VecNormalize(hit -> isect_normal) ;
- X
- X return(1) ;
- X}
- X
- Xint
- XTriNormal(obj, hit, P, N)
- X Object * obj ;
- X Isect * hit ;
- X Point P, N ;
- X{
- X VecCopy(hit -> isect_normal, N) ;
- X}
- X
- XObject *
- XMakeTri(point)
- X Vec *point ;
- X{
- X Object * o ;
- X TriData * td ;
- X Vec N, P, Q;
- X int i, j ;
- X Flt dmin, dmax, d ;
- X Vec B[3] ;
- X
- X o = (Object *) malloc (sizeof(Object)) ;
- X o -> o_type = T_TRI ;
- X o -> o_procs = & TriProcs ;
- X o -> o_surf = CurrentSurface ;
- X
- X td = (TriData *) malloc (sizeof(TriData)) ;
- X
- X /*
- X * copy in the points....
- X */
- X VecCopy(point[0], td -> tri_P[0]) ;
- X VecCopy(point[2], td -> tri_P[1]) ;
- X VecCopy(point[4], td -> tri_P[2]) ;
- X
- X /*
- X * and the normals, then normalize them...
- X */
- X VecCopy(point[1], td -> tri_N[0]) ;
- X VecCopy(point[3], td -> tri_N[1]) ;
- X VecCopy(point[5], td -> tri_N[2]) ;
- X VecNormalize(td -> tri_N[0]) ;
- X VecNormalize(td -> tri_N[1]) ;
- X VecNormalize(td -> tri_N[2]) ;
- X
- X /*
- X * construct the inverse of the matrix...
- X * | P1 |
- X * | P2 |
- X * | N |
- X * and store it in td -> tri_bb[]
- X */
- X
- X VecSub(td -> tri_P[1], td -> tri_P[0], B[0]) ;
- X VecSub(td -> tri_P[2], td -> tri_P[0], B[1]) ;
- X VecCross(B[0], B[1], B[2]) ;
- X VecNormalize(B[2]) ;
- X
- X InvertMatrix(B, td -> tri_bb) ;
- X
- X for (i = 0 ; i < NSLABS ; i ++) {
- X dmin = HUGE ;
- X dmax = - HUGE ;
- X
- X for (j = 0 ; j < 3 ; j ++) {
- X d = VecDot(Slab[i], td -> tri_P[j]) ;
- X if (d < dmin) dmin = d ;
- X if (d > dmax) dmax = d ;
- X }
- X o -> o_dmin[i] = dmin - rayeps ;
- X o -> o_dmax[i] = dmax + rayeps ;
- X }
- X
- X o -> o_data = (void *) td ;
- X
- X return o ;
- X}
- X
- XInvertMatrix(in, out)
- X Vec in[3] ;
- X Vec out[3] ;
- X{
- X int i, j, k ;
- X Flt tmp, det, sum ;
- X
- X out[0][0] = (in[1][1] * in[2][2] - in[1][2] * in[2][1]) ;
- X out[1][0] = -(in[0][1] * in[2][2] - in[0][2] * in[2][1]) ;
- X out[2][0] = (in[0][1] * in[1][2] - in[0][2] * in[1][1]) ;
- X
- X out[0][1] = -(in[1][0] * in[2][2] - in[1][2] * in[2][0]) ;
- X out[1][1] = (in[0][0] * in[2][2] - in[0][2] * in[2][0]) ;
- X out[2][1] = -(in[0][0] * in[1][2] - in[0][2] * in[1][0]) ;
- X
- X out[0][2] = (in[1][0] * in[2][1] - in[1][1] * in[2][0]) ;
- X out[1][2] = -(in[0][0] * in[2][1] - in[0][1] * in[2][0]) ;
- X out[2][2] = (in[0][0] * in[1][1] - in[0][1] * in[1][0]) ;
- X
- X det =
- X in[0][0] * in[1][1] * in[2][2] +
- X in[0][1] * in[1][2] * in[2][0] +
- X in[0][2] * in[1][0] * in[2][1] -
- X in[0][2] * in[1][1] * in[2][0] -
- X in[0][0] * in[1][2] * in[2][1] -
- X in[0][1] * in[1][0] * in[2][2] ;
- X
- X det = 1 / det ;
- X
- X for (i = 0 ; i < 3 ; i ++) {
- X for (j = 0 ; j < 3 ; j++) {
- X out[i][j] *= det ;
- X }
- X }
- X
- X#ifdef DEBUG
- X for (i = 0 ; i < 3 ; i++) {
- X for (j = 0 ; j < 3 ; j++) {
- X sum = 0.0 ;
- X for (k = 0 ; k < 3 ; k++) {
- X sum += in[i][k] * out[k][j] ;
- X }
- X if (fabs(sum) < rayeps) {
- X sum = 0.0 ;
- X }
- X printf(" %g") ;
- X }
- X printf("\n") ;
- X }
- X printf("\n") ;
- X#endif /* DEBUG */
- X}
- END_OF_FILE
- if test 6022 -ne `wc -c <'tri.c'`; then
- echo shar: \"'tri.c'\" unpacked with wrong size!
- fi
- # end of 'tri.c'
- fi
- echo shar: End of archive 2 \(of 3\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 3 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 3 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-